home *** CD-ROM | disk | FTP | other *** search
- /* File: TestFinderLaunch.c
-
- Description:
- A test application for sending an open documents Apple event to the
- Finder. This application calls the FinderLaunch routine defined
- in FinderLaunch.c.
-
- This file is organized into the following sections:
-
- HFS OBJECT SELECTION
- routines calling Navigation Services or Standard file allowing
- the user to select either a file or a directory.
- CALLING FinderLaunch
- a routine that calls the FinderLaunch routine defined in the file
- FinderLaunch.c. Here, after gathering a list of files/folders
- from the user, an open documents apple event is sent to the
- Finder specifying the items selected. The Finder, in turn,
- with launch/display/open the items as appropriate.
- MAIN WINDOW
- routines for drawing and handling clicks in the main window.
- MENU HANDLING
- menu handleing code
- APPLE EVENT HANDLERS
- apple event handlers for open and quit application events.
- EVENT HANDLING
- event dispatching code. calls to WaitNextEvent are made here.
- MAIN PROGRAM
- the main program routine including initialization code, the main
- loop, and teardown code.
-
- Author: John Montbriand
-
- Copyright:
- Copyright © 1999 by Apple Computer, Inc.
- All rights reserved worldwide.
-
- Disclaimer:
- You may incorporate this sample code into your applications without
- restriction, though the sample code has been provided "AS IS" and the
- responsibility for its operation is 100% yours. However, what you are
- not permitted to do is to redistribute the source as "DSC Sample Code"
- after having made changes. If you're going to re-distribute the source,
- we require that you make it clear in the source that the code was
- descended from Apple Sample Code, but that you've made changes.
-
- Change History (most recent first):
- 9/13/99 created by John Montbriand
- */
-
- #include "TestFinderLaunch.h"
- #include "FinderLaunch.h"
-
- #include <QuickDraw.h>
- #include <Menus.h>
- #include <Windows.h>
- #include <Dialogs.h>
- #include <Fonts.h>
- #include <SegLoad.h>
- #include <Resources.h>
- #include <Balloons.h>
- #include <Devices.h>
- #include <AppleEvents.h>
- #include <StdIO.h>
- #include <TextUtils.h>
- #include <string.h>
- #include <Gestalt.h>
- #include <Appearance.h>
-
- #include <StandardFile.h>
- #include <Navigation.h>
-
-
- /* true while the app is running */
- Boolean gRunning = true;
-
- #ifndef __MWERKS__
- QDGlobals qd; /* QuickDraw globals*/
- #endif
-
- FileFilterYDUPP gFileFilter;
- DlgHookYDUPP gSFHook;
- NavEventUPP gNavEventProc;
- AEIdleUPP gAEIdleProc = NULL; /* idle proc called from AEInteractWithUser */
- DialogPtr gMainDialog = NULL;
-
- Boolean gForground = true;
- Boolean gAppleEvents = false;
- Boolean gAppearance = false;
-
-
-
- /* HFS OBJECT SELECTION ------------------------------------------------ */
-
- /* in this section we define a set of routines for selecting a file or a folder.
- Here, NavigationServices is used when it is present, otherwise we fall
- back to useing the standard file alerts for system 7. Note that Navigation
- services is strictly PowerPC only, so any parts referring to that API are
- bracketed in conditional statements.
-
- These routines are here so there is a way to choose a file or folder from the
- main application. After selecting a file or folder, an Apple event is sent to
- the finder asking it to open/launch/display the item. */
-
-
- /* InvisoFilter is a file filter procedure passed to the CustomGetFile routine. Its
- purpose is to prevent the display of invisible files and folders in the
- standard file window. */
- static pascal Boolean InvisoFilter(ParmBlkPtr PB, void *yourDataPtr) {
- CInfoPBRec *cat = (CInfoPBRec *) PB;
- /* filter invisible files and folders */
- if ((cat->hFileInfo.ioFlFndrInfo.fdFlags & kIsInvisible) == 0)
- return false;
- else return true;
- }
-
- /* MySFHook is a dialog hook routine passed to the CustomGetFile routine. Its purpose
- is to maintain the 'Select' button in the bottom right corner of the window. This
- button allows users to select a directory rather than navigate into it. If the
- user clicks on the 'Select' button while a folder is hilited in the list view, then
- the folder is passed back to CustomGetFile's caller. */
- static pascal short MySFHook(short item, DialogPtr dialog, void *yourDataPtr) {
-
- static Boolean gFolderSelected = false;
- static ControlHandle gFolderControl = NULL;
- StandardFileReply *theReply;
-
- if (GetWRefCon(dialog) != sfMainDialogRefCon) return item;
- theReply = (StandardFileReply *) yourDataPtr;
- if (item == sfHookFirstCall) {
- short itemt;
- Rect itemb;
- GetDialogItem(dialog, kMySFSelectButton, &itemt, (Handle*) &gFolderControl, &itemb);
- HiliteControl(gFolderControl, 255);
- gFolderSelected = false;
- } else if ((item == kMySFSelectButton) && gFolderSelected) {
- return sfItemOpenButton;
- } else {
- if (theReply->sfIsFolder || theReply->sfIsVolume) {
- if ( ! gFolderSelected) {
- HiliteControl(gFolderControl, 0);
- gFolderSelected = true;
- }
- } else if (gFolderSelected) {
- HiliteControl(gFolderControl, 255);
- gFolderSelected = false;
- }
- }
- return item;
- }
-
-
- #if TARGET_CPU_PPC
-
- /* NavEventCallBack is a callback routine provided to the NavChooseObject routine. In
- this routine we process update and activate events for the main window while
- navigation services is displaying its window. */
- static pascal void NavEventCallBack( NavEventCallbackMessage callBackSelector,
- NavCBRecPtr callBackParms, NavCallBackUserData callBackUD) {
- if (callBackSelector == kNavCBEvent) {
- short ewhat;
- ewhat = callBackParms->eventData.eventDataParms.event->what;
- if ((ewhat == updateEvt) || (ewhat == activateEvt)) {
-
- HandleNextEvent(callBackParms->eventData.eventDataParms.event);
-
- }
- }
- }
-
- #endif
-
-
- /* GetHFSObjectList opens a communication session with the user allowing them to choose
- one more file system objects. After the user has made a selection, a list of the items
- chosen is passed back as a AEDescList containing a list of FSSpec records. if the user
- cancels the interaction, then no list is returned and a userCanceledErr is returned.*/
- static OSErr GetHFSObjectList(AEDescList *documents) {
- #if TARGET_CPU_PPC
- NavReplyRecord theReply;
- #endif
- Boolean hasNavReply;
- OSErr err;
- /* set up locals */
- AECreateDesc(typeNull, NULL, 0, documents);
- hasNavReply = false;
-
- #if TARGET_CPU_PPC
- if (NavServicesAvailable()) {
- NavDialogOptions dialogOptions;
- /* set the message in the navigation window to indicated multiple
- selections are allowed */
- memset(&theReply, 0, sizeof(theReply));
- err = NavGetDefaultDialogOptions(&dialogOptions);
- if (err != noErr) goto bail;
- dialogOptions.dialogOptionFlags = (kNavDontAutoTranslate | kNavAllowMultipleFiles);
- GetIndString(dialogOptions.message, kMainStrings, kNavTextMessage);
- /* run the navigation window */
- err = NavChooseObject( NULL, &theReply, &dialogOptions, gNavEventProc, NULL, NULL);
- if (err != noErr) goto bail;
- if (!theReply.validRecord) { err = userCanceledErr; goto bail; }
- hasNavReply = true;
- /* duplicate the returned document list */
- err = AEDuplicateDesc(&theReply.selection, documents);
- if (err != noErr) goto bail;
- /* clean up the navigation stuff */
- NavDisposeReply(&theReply);
- } else
- #endif
- { Point where = {100, 100};
- SFTypeList typeList;
- StandardFileReply reply;
- /* set up locals
- SetPt(&where, 100, 100);
- /* run the standard file window */
- CustomGetFile(gFileFilter, -1, typeList, &reply, 130, where, gSFHook, NULL, NULL, NULL, &reply);
- if (!reply.sfGood) { err = userCanceledErr; goto bail; }
- /* if successful, save the selection to a list descriptor */
- err = AECreateList(NULL, 0, false, documents);
- if (err != noErr) goto bail;
- err = AEPutPtr(documents, 0, typeFSS, &reply.sfFile, sizeof(FSSpec));
- if (err != noErr) goto bail;
- }
- return noErr;
-
- /* error recovery */
- bail:
- #if TARGET_CPU_PPC
- if (hasNavReply) NavDisposeReply(&theReply);
- #endif
- AEDisposeDesc(documents);
- return err;
- }
-
-
-
- /* CALLING FinderLaunch ------------------------------------------------ */
-
- /* in this section, we call through to the FinderLaunch() routine defined in the
- file FinderLaunch.c. After calling GetHFSObjectList to retrieve a list of one or
- more FSSpec records referring to a number of hfs objects, we coerce this list
- into an array of FSSpec records and pass it to the FinderLaunch routine. */
-
-
- /* SelectTargetsToLaunch calls GetHFSObjectList to retrieve a list of files or folders
- and then it passes the selected folders and files to the FinderLaunch routine. */
- static void SelectTargetsToLaunch(void) {
- AEDescList documents;
- OSErr err;
- long index, count;
- FSSpec *targets;
- AEKeyword keyword;
- DescType typecode;
- Size actualSize;
- /* set up locals */
- AECreateDesc(typeNull, NULL, 0, &documents);
- targets = NULL;
- /* get a list of files from the user */
- err = GetHFSObjectList(&documents);
- if (err != noErr) goto bail;
- /* count the items in the list */
- err = AECountItems(&documents, &count);
- if (err != noErr) goto bail;
- /* allocate an array to store the records */
- targets = (FSSpec *) NewPtr(count * sizeof(FSSpec));
- if (targets == NULL) { err = memFullErr; goto bail; }
- /* copy each record from the list to the array */
- for (index = 0; index < count; index++) {
- err = AEGetNthPtr(&documents, (index + 1), typeFSS, &keyword, &typecode,
- (targets + index), sizeof(FSSpec), &actualSize);
- if (err != noErr) goto bail;
- }
- /* ask the Finder to launch the items */
- err = FinderLaunch(count, targets);
-
- /* clean up and leave, report any 'real' errors */
- bail:
- if ((err != noErr) && (err != userCanceledErr)) {
- Str255 errStr;
- NumToString(err, errStr);
- ParamAlert(kSelectAbortedError, errStr, NULL);
- }
- if (targets != NULL) DisposePtr((Ptr) targets);
- AEDisposeDesc(&documents);
- }
-
-
-
-
-
- /* MAIN WINDOW ------------------------------------------------ */
-
-
- /* HitMainWindow is called when DialogSelect returns true for the main
- dialog window. This usually indicates that there has been a mouse
- down inside of the main window. */
- static void HitMainWindow(DialogPtr theDialog, EventRecord *ev, short itemNo) {
- if (itemNo == kMainSelectButton)
- SelectTargetsToLaunch();
- }
-
-
- /* RedrawMainDialogWindow redraws the main window honoring the current
- activation state of the window. */
- static void RedrawMainDialogWindow(DialogPtr theDialog) {
- if (theDialog != NULL) {
- short itemt;
- ControlHandle theControl;
- Rect itemb;
-
- GetDialogItem(theDialog, kMainSelectButton, &itemt, (Handle*) &theControl, &itemb);
- if ((theDialog == FrontWindow()) && gForground)
- HiliteControl(theControl, 0);
- else HiliteControl(theControl, 255);
- DrawDialog(theDialog);
- }
- }
-
-
-
- /* MENU HANDLING ------------------------------------------------ */
-
-
- /* ResetMenus is called to reset the menus immediately before
- either MenuSelect or MenuKey is called. Here, we disable the
- quit command during file copies. */
- static void ResetMenus(void) {
- /* nothing to do here */
- }
-
-
- /* DoMenuCommand is called after either MenuSelect of MenuKey. The
- parameter rawMenuSelectResult is the result from one of these two routines.
- DoMenuCommand parses this result into its two parts, and dispatches
- the menu command as appropriate. */
- static void DoMenuCommand(long rawMenuSelectResult) {
- short menu, item;
- /* decode the MenuSelect result */
- menu = (rawMenuSelectResult >> 16);
- if (menu == 0) return;
- item = (rawMenuSelectResult & 0x0000FFFF);
- /* dispatch on result */
- switch (menu) {
- case mApple:
- if (item == iAbout) {
- /* show the about box. */
- ParamAlert(kAboutBoxError, NULL, NULL);
- } else if (item >= iFirstAppleItem) {
- Str255 deskAccName;
- /* open an apple menu item. */
- GetMenuItemText(GetMenuHandle(mApple), item, deskAccName);
- OpenDeskAcc(deskAccName);
- }
- break;
- case mFile:
- if (item == iSelectTargets)
- SelectTargetsToLaunch();
- else if (item == iQuit)
- gRunning = false;
- break;
- }
- /* unhilite the menu once we're done the command */
- HiliteMenu(0);
- }
-
-
-
- /* APPLE EVENT HANDLERS ------------------------------------------------ */
-
- /* OpenApplication is an apple event handler called for 'open application' apple events. */
- static pascal OSErr OpenApplication(const AppleEvent *appleEvt, AppleEvent* reply, long refcon) {
- gMainDialog = GetNewDialog(kMainDialog, NULL, (WindowPtr) (-1));
- return noErr;
- }
-
- /* CloseApplication is an apple event handler called for 'close application' apple events. */
- static pascal OSErr CloseApplication(const AppleEvent *appleEvt, AppleEvent* reply, long refcon) {
- gRunning = false;
- return noErr;
- }
-
-
-
- /* EVENT HANDLING ------------------------------------------------ */
-
-
- /* HandleNextEvent handles the event in the event record *ev dispatching
- the event to appropriate routines. */
- void HandleNextEvent(EventRecord *ev) {
- DialogPtr theDialog;
- WindowPtr theWindow;
- short itemNo;
-
- /* dialog pre-processing */
- if (((ev->what == keyDown) || (ev->what == autoKey)) && ((ev->modifiers & cmdKey) != 0)) {
- ResetMenus();
- DoMenuCommand(MenuKey((char) (ev->message & charCodeMask)));
- } else if (ev->what == osEvt) {
- /* process manager switches */
- if ( (((ev->message >> 24) & 0x0FF) == suspendResumeMessage) && ((ev->message & resumeFlag) != 0)) {
- gForground = true;
- } else gForground = false;
- RedrawMainDialogWindow(gMainDialog);
- } else if (ev->what == activateEvt) {
- if ((gMainDialog == ((DialogPtr) ev->message)))
- RedrawMainDialogWindow(gMainDialog);
- }
-
- /* handle clicks in the dialog window */
- if (IsDialogEvent(ev))
- if (DialogSelect(ev, &theDialog, &itemNo)) {
- if (theDialog == gMainDialog)
- HitMainWindow(theDialog, ev, itemNo);
- }
-
- /* clicks and apple events... */
- if (ev->what == kHighLevelEvent) {
- AEProcessAppleEvent(ev);
- } else if (ev->what == mouseDown)
- switch (FindWindow(ev->where, &theWindow)) {
-
- /* menu bar clicks */
- case inMenuBar:
- ResetMenus();
- DoMenuCommand(MenuSelect(ev->where));
- break;
-
- /* clicks in the close box, close the app */
- case inGoAway:
- if (TrackGoAway(theWindow, ev->where)) {
- gRunning = false;
- }
- break;
-
- /* allow window drags */
- case inDrag:
- if (theWindow == FrontWindow()) {
- Rect boundsRect = { -32000, -32000, 32000, 32000};
- DragWindow(theWindow, ev->where, &boundsRect);
- }
- break;
-
- /* desktop clicks, etc... */
- case inSysWindow:
- SystemClick(ev, theWindow);
- break;
- }
- }
-
-
- /* ProcessNextEvent calls WaitNextEvent to get the next event and then it passes
- the event along to the HandleNextEvent routine. sleepTime is passed to the
- WaitNextEvent routine in the sleep parameter. */
- void ProcessNextEvent(long sleepTime) {
- EventRecord ev;
- /* get the next event */
- if ( ! WaitNextEvent(everyEvent, &ev, sleepTime, NULL) )
- ev.what = nullEvent;
- HandleNextEvent(&ev);
- }
-
- /* FDPIdleProcedure is the idle procedure called by AEInteractWithUser while we are waiting
- for the application to be pulled into the forground. It simply passes the event along
- to HandleNextEvent */
- static pascal Boolean FDPIdleProcedure(EventRecord *theEvent, long *sleepTime, RgnHandle *mouseRgn) {
- HandleNextEvent(theEvent);
- return false;
- }
-
-
- /* ParamAlert is a general alert handling routine. If Apple events exist, then it
- calls AEInteractWithUser to ensure the application is in the forground, and then
- it displays an alert after passing the s1 and s2 parameters to ParamText. */
- short ParamAlert(short alertID, StringPtr s1, StringPtr s2) {
- AEInteractWithUser(kNoTimeOut, NULL, gAEIdleProc);
- ParamText(s1, s2, NULL, NULL);
- return Alert(alertID, NULL);
- }
-
-
-
- /* MAIN PROGRAM ------------------------------------------------ */
-
- int main(void) {
- OSErr err;
- AEEventHandlerUPP aehandler;
- long response;
-
- /* set up our app */
- SetApplLimit(GetApplLimit());
- MaxApplZone();
- InitGraf(&qd.thePort);
- InitFonts();
- InitWindows();
- TEInit();
- InitMenus();
- InitDialogs(0);
- FlushEvents(everyEvent, 0);
- InitCursor();
-
-
- /* apple events??? */
- if (Gestalt(gestaltAppleEventsAttr, &response) != noErr) response = 0;
- gAppleEvents = ((response & (1<<gestaltAppleEventsPresent)) != 0);
- if ( ! gAppleEvents) {
- ParamAlert(kReqMgrsNotAvailError, NULL, NULL);
- err = userCanceledErr;
- goto bail;
- }
- /* appearance */
- if (Gestalt(gestaltAppearanceAttr, &response) != noErr) response = 0;
- if ((response & (1<<gestaltAppearanceExists)) != 0) {
- err = RegisterAppearanceClient();
- if (err != noErr) goto bail;
- gAppearance = true;
- }
-
- #if TARGET_CPU_PPC
- if (NavServicesAvailable())
- NavLoad();
- gNavEventProc = NewNavEventProc(NavEventCallBack);
- if (gNavEventProc == NULL) { err = memFullErr; goto bail; }
- #endif
- gFileFilter = NewFileFilterYDProc(InvisoFilter);
- if (gFileFilter == NULL) { err = memFullErr; goto bail; }
- gSFHook = NewDlgHookYDProc(MySFHook);
- if (gSFHook == NULL) { err = memFullErr; goto bail; }
- gAEIdleProc = NewAEIdleProc(FDPIdleProcedure);
- if (gAEIdleProc == NULL) { err = memFullErr; goto bail; }
-
- /* standard apple events */
- aehandler = NewAEEventHandlerProc(OpenApplication);
- if (aehandler == NULL) { err = memFullErr; goto bail; }
- err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, aehandler, 0, false);
- if (err != noErr) goto bail;
- aehandler = NewAEEventHandlerProc(CloseApplication);
- if (aehandler == NULL) { err = memFullErr; goto bail; }
- err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, aehandler, 0, false);
- if (err != noErr) goto bail;
-
- /* set up the menu bar */
- SetMenuBar(GetNewMBar(128));
- DrawMenuBar();
- AppendResMenu(GetMenuHandle(mApple), 'DRVR');
-
- /* run the app */
- while (gRunning) {
-
- ProcessNextEvent(-1);
-
- }
-
- bail:
- #if TARGET_CPU_PPC
- if (NavServicesAvailable())
- NavUnload();
- #endif
- if (err != noErr && err != userCanceledErr) {
- Str255 errStr;
- NumToString(err, errStr);
- ParamAlert(kProgramAbortedError, errStr, NULL);
- }
- if (gAppearance)
- UnregisterAppearanceClient();
- ExitToShell();
- return 0;
- }